#include "SingletonConnectionPool.h"

ConnectionPool::ConnectionPool()
{
}

void ConnectionPool::init(std::string ip, uint16_t port, std::string user, std::string password, std::string database,
                          int maxSize, int timeout)
{
    m_ip = ip;
    m_port = port;
    m_user = user;
    m_password = password;
    m_database = database;
    m_max_size = maxSize;
    m_timeout = timeout;

    m_driver = sql::mysql::get_driver_instance();

    for (int i = 0; i < m_max_size; i++)
    {
        addConnection();
    }
}

void ConnectionPool::addConnection()
{
    sql::Connection *conn = m_driver->connect("tcp://" + m_ip + ":" + std::to_string(m_port) + "/" + m_database, m_user, m_password);
    if (conn)
    {
        m_connection_queue.push(conn);
    }
}

std::shared_ptr<sql::Connection> ConnectionPool::getConnection() {
    std::unique_lock<std::mutex> lock(m_mutex);
    while(m_connection_queue.empty()) {
        if(m_cond.wait_for(lock, std::chrono::milliseconds(m_timeout)) == std::cv_status::timeout) {
            continue;
        }
    }

    std::shared_ptr<sql::Connection> conn(m_connection_queue.front(), [this](sql::Connection* conn){
        std::unique_lock<std::mutex> lock(m_mutex);
        m_connection_queue.push(conn);
    });
    m_connection_queue.pop();
    m_cond.notify_all();
    return conn;
}